package chamster;

import java.awt.Point;
import java.util.Random;

import chamster.view.HamsterView;
import de.hamster.debugger.model.Territorium;
import de.hamster.debugger.model.Hamster;
/**
 * Base class for all hamster model
 * @author mark
 *
 */
public abstract class BaseHamster {
	
	private final Hamster hamster;
	private final HamsterView view;
	private final int numberOfGrain;
	private boolean viewTainted;
	/**
	 * charge
	 */
	private int charge;
	
	public BaseHamster() {
		this.hamster = new Hamster();
		this.viewTainted = true;
		Point start = BaseHamster.getStartPoint();
		this.hamster.init(start.y, start.x, Hamster.EAST, 0);
		this.view = new HamsterView(this.hamster, 
				Territorium.getAnzahlSpalten(),
				Territorium.getAnzahlReihen());
		this.charge = Territorium.getAnzahlReihen() 
				* Territorium.getAnzahlSpalten() * 4;
		this.numberOfGrain = Territorium.getAnzahlKoerner();
		this.view.updateView();
	}
	
	public boolean canMoveForeward() {
		return this.hamster.vornFrei();
	}
	
	public void foreward() throws Exception {
		this.decrementCharge(1);
		this.hamster.vor();
		this.viewTainted = true;
	}
	
	public void turnRight() throws Exception {
		this.decrementCharge(1);
		for(int i = 0; i < 3; i++) {
			this.hamster.linksUm();
		}
		this.viewTainted = true;
	}
	
	public void turnAround() throws Exception {
		this.decrementCharge(2);
		for(int i = 0; i < 2; i++) {
			this.hamster.linksUm();
		}
		this.viewTainted = true;

	}
	
	public void turnLeft() throws Exception {
		this.decrementCharge(1);
		this.hamster.linksUm();
		this.viewTainted = true;
	}
	
	private void decrementCharge(int decrement) throws Exception {
		this.charge = this.charge - decrement;
		if(this.charge < 0) {
			throw new Exception("Accu is empty");
		}
	}
	
	public void main() {
		try {
			this.life();
		} catch (Exception e) {
			e.printStackTrace();
			this.hamster.schreib(e.getMessage());
		}
		this.printStat();
	}
	
	public abstract void life() throws Exception;
	
	private void printStat() {
		String message = "Hamster finished\n" +
				"There were " + this.numberOfGrain + " corns.\n" +
				"The hamster collected " + 
				this.hamster.getAnzahlKoerner() + " of them.\n"+
				"Remaining charge " + this.charge + ".";
		this.hamster.schreib(message);
	}
	
	public HamsterView getView() {
		if(this.viewTainted) {
			this.view.updateView();
			this.viewTainted = false;
		}
		return this.view;
	}
	
	public boolean chargeLeft(int actions) {
		return this.charge - actions > 0;
	}
	
	public boolean canPickup() {
		return this.hamster.kornDa();
	}
	
	public void pickup() throws Exception {
		this.hamster.nimm();
	}
	
	public Point getLocation() {
		return new Point(this.hamster.getSpalte(), this.hamster.getReihe());
	}
	
	/**
	 * Calling the Territorium method from outside of the hamster class fails.
	 * @param p
	 * @return
	 */
	public static boolean isWallAt(Point p) {
		return Territorium.mauerDa(p.y, p.x);
	}
	
	public static Point getStartPoint() {
		Random ran = new Random();
		int x = ran.nextInt(Territorium.getAnzahlSpalten());
		int y = ran.nextInt(Territorium.getAnzahlReihen());
		while(BaseHamster.isWallAt(new Point(x, y))) {
			x = ran.nextInt(Territorium.getAnzahlSpalten());
			y = ran.nextInt(Territorium.getAnzahlReihen());
		}
		return new Point(x, y);
	}
}
